The Box API provides a great way to securely connect your application to the Box platform.
The Box Python SDK makes consuming the API an easy task. Let's see how easy it is to get started.
To begin, we need 3 things:
You can get all 3 at http://developers.box.com - if you don't already have a Box application, you can sign up for one there.
For this demo, I wrote these 3 things to a text file called app.cfg
.
Finally, we need to install the SDK:
pip install boxsdk
Now we can start writing some code.
In [1]:
# Import two classes from the boxsdk module - Client and OAuth2
from boxsdk import Client, OAuth2
# Define client ID, client secret, and developer token.
CLIENT_ID = None
CLIENT_SECRET = None
ACCESS_TOKEN = None
# Read app info from text file
with open('app.cfg', 'r') as app_cfg:
CLIENT_ID = app_cfg.readline()
CLIENT_SECRET = app_cfg.readline()
ACCESS_TOKEN = app_cfg.readline()
The Python SDK is organized into layers:
For demonstration purposes, I'm subclassing the default network layer to log network requests and responses.
In [2]:
from boxsdk.network.default_network import DefaultNetwork
from pprint import pformat
class LoggingNetwork(DefaultNetwork):
def request(self, method, url, access_token, **kwargs):
""" Base class override. Pretty-prints outgoing requests and incoming responses. """
print '\x1b[36m{} {} {}\x1b[0m'.format(method, url, pformat(kwargs))
response = super(LoggingNetwork, self).request(
method, url, access_token, **kwargs
)
if response.ok:
print '\x1b[32m{}\x1b[0m'.format(response.content)
else:
print '\x1b[31m{}\n{}\n{}\x1b[0m'.format(
response.status_code,
response.headers,
pformat(response.content),
)
return response
In [3]:
# Create OAuth2 object. It's already authenticated, thanks to the developer token.
oauth2 = OAuth2(CLIENT_ID, CLIENT_SECRET, access_token=ACCESS_TOKEN)
# Create the authenticated client
client = Client(oauth2, LoggingNetwork())
We now have a fully authenticated SDK client!
Let's try it out.
The SDK's Client object contains a collection of methods that allow you to instantiate Box objects and endpoints.
client.folder(folder_id)
client.file(file_id)
client.events()
client.search()
client.user(user_id)
Once you have a Box object, you can get()
information about it, or do various operations (delete()
, or upload/download).
Let's look at the User
object.
In [4]:
# Get information about the logged in user (that's whoever owns the developer token)
my = client.user(user_id='me').get()
print my.name
print my.login
print my.avatar_url
Now let's look at some different objects, like File
and Folder
.
client.folder('0')
is a reference to the root folder ("All Files").
In [5]:
root_folder = client.folder('0')
root_folder_with_info = root_folder.get()
In [6]:
# Save time and bandwidth by only asking for the folder owner
root_folder_with_limited_info = root_folder.get(fields=['owned_by'])
The SDK makes it very easy to download and upload files.
Folder.upload(file_path ,filename)
uploads a file to that folder, and Folder.upload_stream(stream, filename)
uploads the contents of a stream as a file to the folder. Both methods return a File
object.
In [7]:
# Upload a file to Box!
from StringIO import StringIO
stream = StringIO()
stream.write('Box Python SDK test!')
stream.seek(0)
box_file = client.folder('0').upload_stream(stream, 'box-python-sdk-test.txt')
print box_file.name
In [8]:
# Download the file's contents from Box
print box_file.content()
print box_file.id
The SDK provides information when an API call couldn't be completed.
Let's try to upload the same file again - this time, the upload will fail! That's because the name is already in use.
In [9]:
stream.seek(0)
box_file = client.folder('0').upload_stream(stream, 'box-python-sdk-test.txt')
The Pre-flight check API will verify that a file will be accepted by Box before you send all the bytes over the wire. It can be used for both first-time uploads, and uploading new versions of an existing File (on /files/[id]/content). If the call returns a 200, then you can proceed with a standard upload call. Preflight checks verify all permissions as if the file was actually uploaded including:
In [12]:
stream.seek(0)
from boxsdk.exception import BoxAPIException
try:
box_file = client.folder('0').upload_stream(stream, 'box-python-sdk-test.txt', preflight_check=True)
except BoxAPIException:
pass
In [13]:
# See if we can find the file on Box using search (may need to wait for Box to index the file)
results = client.search('Box Python SDK test', 2, 0)
matching_results = (r for r in results if r.id == box_file.id)
for m in matching_results:
print m.name
print m.created_at
break
else:
print 'No match found'